package ldh.im.admin.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;

import ldh.common.PageResult;
import ldh.im.admin.config.AesService;
import ldh.im.admin.constant.LogType;
import ldh.im.admin.dao.UserDao;
import ldh.im.admin.dao.UserRoleDao;
import ldh.im.admin.exception.BusinessException;
import ldh.im.admin.exception.DbErrorType;
import ldh.im.admin.pojo.Role;
import ldh.im.admin.pojo.User;
import ldh.im.admin.pojo.UserRole;
import ldh.im.admin.pojo.where.UserWhere;
import ldh.im.admin.util.NumberUtil;
import ldh.im.admin.util.RegexUtil;
import ldh.im.admin.util.UserUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author: ldh
 * @date: 2019-10-25 12:35:06
 */
@Service("userService")
public class UserService {

	@Resource
	private UserDao userDao;
	@Resource
	private LogService logService;
	@Resource
	private UserRoleDao userRoleDao;
	@Resource
	private AesService aesService;

	@Transactional
	public User insert(User user) {
		int n = userDao.insert(user);
		if (n != 1) {
			throw new RuntimeException("User insert error!");
		}
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.create_user, "创建新用户");
		return user;
	}

	@Transactional
	public void userChangePassword(User user) {
		updateById(user);
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.change_password, "用户重置密码");
	}

	@Transactional
	public String changePassword(Long id) throws Exception {
		User user = getById(id);
		String salt = RandomStringUtils.randomAlphabetic(10);
		String newPassword = RandomStringUtils.randomAlphabetic(16);
		String passwordEncode = UserUtil.encodePassword(aesService, newPassword, salt);
		user.setSalt(salt);
		user.setPassword(passwordEncode);
		user.setUpdateTime(new Date());
		updateById(user);
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.change_password, "重置用户密码");
		return newPassword;
	}

	@Transactional
	public User updateById(User user) {
		int n = userDao.updateById(user);
		if (n != 1) {
			throw new RuntimeException("User update error!");
		}
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.edit_user, "更新用户");
		return user;
	}

	@Transactional
	public User updateNotNullById(User user) {
		int n = userDao.updateNotNullById(user);
		if (n != 1) {
			throw new RuntimeException("User update error!");
		}
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.edit_user, "更新用户");
		return user;
	}

	@Transactional
	public void deleteById(Long id) {
		User user = getById(id);
		int n = userDao.deleteById(id);
		if (n != 1) {
			throw new RuntimeException("User delete error!");
		}
		logService.insert(getByKey(UserUtil.getLoginUser()), user, LogType.delete_user, "删除用户");
	}

	@Transactional(readOnly = true)
	public User getByUserName(String userName, boolean isJoin) {
		if (!isJoin) return userDao.getByUserNameOnly(userName);
		User user = userDao.getByUserName(userName);
		return user;
	}

	@Transactional(readOnly = true)
	public User getByUserName(String userName) {
		return getByUserName(userName, true);
	}

	@Transactional(readOnly = true)
	public User getByPhone(String phone) {
		return getByPhone(phone, true);
	}

	@Transactional(readOnly = true)
	public User getByPhone(String phone, boolean isJoin) {
		if (!isJoin) return userDao.getByPhoneOnly(phone);
		User user = userDao.getByPhone(phone);
		return user;
	}

	@Transactional(readOnly = true)
	public User getByEmail(String email) {
		User user = userDao.getByEmail(email);
		return user;
	}

	@Transactional(readOnly = true)
	public User getByEmail(String email, boolean isJoin) {
		if (!isJoin) return userDao.getByEmailOnly(email);
		User user = userDao.getByEmail(email);
		return user;
	}

	@Transactional(readOnly = true)
	public User getById(Long id) {
		User user = userDao.getJoinById(id);
		return user;
	}

	@Transactional(readOnly = true)
	public List<User> getByIds(List<Long> ids) {
		if (ids.size() == 0) return new ArrayList<>();
		List<User> users = userDao.getByIds(ids);
		return users;
	}

	@Transactional(readOnly = true)
	public User getByKey(String key) {
		return getByKey(key, true);
	}

	@Transactional(readOnly = true)
	public User getByKey(String key, boolean isJoin) {
		try {
			if (RegexUtil.isPhone(key)) {
				return getByPhone(aesService.encrypt(key), isJoin);
			} else if (RegexUtil.isEmail(key)) {
				return getByEmail(aesService.encrypt(key), isJoin);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		User user = getByUserName(key, isJoin);
		return user;
	}

	@Transactional(readOnly = true)
	public User getAllByKey(String key) {
		User user = userDao.getAllByKey(key);
		return user;
	}

	@Transactional(readOnly = true)
	public User getManyRolesById(Long id) {
		return userDao.getManyRolesById(id);
	}

	@Transactional(readOnly = true)
	public PageResult<User> findByUserWhere(UserWhere userWhere) {
		long total = userDao.findTotalByUserWhere(userWhere);
		List<User> imageList = new ArrayList<User>();
		if (total > 0) {
			imageList = userDao.findByUserWhere(userWhere);
		}

		return new PageResult<User>(userWhere, total, imageList);
	}

	@Transactional(readOnly = true)
	public long findTotalByUserWhere(UserWhere userWhere) {
		long total = userDao.findTotalByUserWhere(userWhere);
		return total;
	}

	@Transactional(readOnly = true)
	public PageResult<User> findJoinByUserWhere(UserWhere userWhere) {
		long total = userDao.findJoinTotalByUserWhere(userWhere);
		List<User> imageList = new ArrayList<User>();
		if (total > 0) {
			imageList = userDao.findJoinByUserWhere(userWhere);
		}

		return new PageResult<User>(userWhere, total, imageList);
	}

	@Transactional
	public void userAuthorize(User user, List<Role> deleteRoleList, List<Role> insertRoleList) {
		for(Role role : deleteRoleList) {
			int n = userRoleDao.deleteByUserIdAndRoleId(user.getId(), role.getId());
			if (n != 1) throw new BusinessException(DbErrorType.Insert_Error, "userAuthorize");
		}

		Date now = new Date();
		List<UserRole> userRoleList = new ArrayList<>();
		for(Role role : insertRoleList) {
			UserRole userRole = new UserRole();
			userRole.setUser(user);
			userRole.setRole(role);
			userRole.setCreateTime(now);

			userRoleList.add(userRole);
		}

		if (userRoleList.size() > 0) {
			int n = userRoleDao.inserts(userRoleList);
			if (n != userRoleList.size()) throw new BusinessException(DbErrorType.Insert_Error, "userAuthorize");
		}
	}

	public void maskUser(User user) {
		try {
			if (user.getEmail() != null) {
				user.setMaskEmail(NumberUtil.maskEmail(aesService.decrypt(user.getEmail())));
			}
			if (user.getPhone() != null) {
				user.setMaskPhone(NumberUtil.maskPhone(aesService.decrypt(user.getPhone())));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
